import java.util.Arrays;

class Solution {
    // public int calculateMinimumHP(int[][] dungeon) {
    // int n = dungeon.length;
    // int m = dungeon[0].length;
    // int[][] dp = new int[n][m];

    // // 处理右下角的最后一个格子
    // dp[n-1][m-1] = Math.max(1 - dungeon[n-1][m-1], 1);

    // // 处理最后一行，从右到左
    // for (int j = m-2; j >= 0; j--) {
    // dp[n-1][j] = Math.max(dp[n-1][j+1] - dungeon[n-1][j], 1);
    // }

    // // 处理最后一列，从下到上
    // for (int i = n-2; i >= 0; i--) {
    // dp[i][m-1] = Math.max(dp[i+1][m-1] - dungeon[i][m-1], 1);
    // }

    // // 处理其他格子，从下到上，从右到左
    // for (int i = n-2; i >= 0; i--) {
    // for (int j = m-2; j >= 0; j--) {
    // int minHealth = Math.min(dp[i+1][j], dp[i][j+1]);
    // dp[i][j] = Math.max(minHealth - dungeon[i][j], 1);
    // }
    // }

    // return dp[0][0];
    // }

    public int calculateMinimumHP(int[][] dungeon) {
        int n = dungeon.length, m = dungeon[0].length;
        int[][] dp = new int[n + 1][m + 1];
        for (int i = 0; i <= n; ++i) {
            Arrays.fill(dp[i], Integer.MAX_VALUE);
        }
        dp[n][m - 1] = dp[n - 1][m] = 1;
        for (int i = n - 1; i >= 0; --i) {
            for (int j = m - 1; j >= 0; --j) {
                int minn = Math.min(dp[i + 1][j], dp[i][j + 1]);
                dp[i][j] = Math.max(minn - dungeon[i][j], 1);
            }
        }
        return dp[0][0];
    }
}